package socket

import (
	"card/constant"
	"encoding/json"
	"fmt"
	"github.com/pkg/errors"
	"reflect"
	"strings"
	"sync"
)

// Hub maintains the set of active clients and broadcasts messages to the
// clients.
type Hub struct {
	sync.RWMutex
	ClientReadChan chan *Request
	Clients        map[*Client]bool
	Handlers       Handler
}

func NewHub() *Hub {
	return &Hub{
		ClientReadChan: make(chan *Request, 1024),
		Clients:        make(map[*Client]bool),
	}
}

func (h *Hub) AddClient(client *Client) {
	defer h.Unlock()
	h.Lock()
	h.Clients[client] = true
}

func (h *Hub) removeClient(client *Client) {
	defer h.Unlock()
	h.Lock()
	_, ok := h.Clients[client]
	if ok {
		client.Close()
		delete(h.Clients, client)
	}
}

func (h *Hub) MessageHandler(client *Client, route string, messageType constant.MessageType, data interface{}) error {
	routers := strings.Split(route, ".")
	if len(routers) != 2 {
		return errors.New("错误的路由")
	}
	handler, ok := h.Handlers[routers[0]]
	if !ok {
		return errors.New("错误的路由")
	}
	method := reflect.ValueOf(handler).MethodByName(routers[1])
	if method.IsValid() {
		return fmt.Errorf("method %v is not exits", method)
	}
	method.Call([]reflect.Value{reflect.ValueOf(client), reflect.ValueOf(messageType), reflect.ValueOf(data)})
	return nil
}
func (h *Hub) ClientReadChanHandler() {
	for {
		select {
		case body, ok := <-h.ClientReadChan:
			if ok {
				h.MessageHandler(body.Client, body.Route, body.Type, body.Data)
			}
		}
	}
}

func (h *Hub) RegisterHandler(handlers Handler) {
	h.Handlers = handlers
}

// 返回
func (h *Hub) Response(data interface{}, client *Client) {
	_, ok := h.Clients[client]
	if ok {
		bytes, err := json.Marshal(data)
		if err != nil {

		}
		client.Send(bytes)
	}
}

// 推送
func (h *Hub) Push(data interface{}, clients []*Client) {
	for _, client := range clients {
		h.Response(data, client)
	}
}
